package socks

import (
	"bufio"
	"fmt"
	"net"
	"sync/atomic"
)

var (
	g_connectId int32 = 1000
)

type SockConn struct {
	id      int32
	isClose atomic.Bool
	addr    net.Addr
	conn    net.Conn

	userData any // 连接存数据的地方，可以存状态

	readBuff *bufio.Reader
	lock     FastLocker

	sendq *SendQueue
}

// 不要 read 方法，在事件中读取数据就可以了
// func (c *SockConn) Read(p []byte) (n int, err error) {
// 	return c.readBuff.Read(p)
// }

func (c *SockConn) Write(p []byte) (n int, err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	return c.conn.Write(p)
}

func (c *SockConn) WriteToQueue(p []byte) (n int, err error) {
	if c.isClose.Load() {
		return 0, fmt.Errorf("connect is closed")
	}

	return c.sendq.Write(p)
}

func (c *SockConn) SendQueueDatas() (int64, error) {
	if c.isClose.Load() {
		return 0, fmt.Errorf("connect is closed")
	}

	c.lock.Lock()
	defer c.lock.Unlock()
	return c.sendq.WriteTo(c.conn)
}

func (c *SockConn) GetData() any {
	c.lock.Lock()
	defer c.lock.Unlock()
	return c.userData
}
func (c *SockConn) SetData(usrData any) {
	c.lock.Lock()
	defer c.lock.Unlock()
	c.userData = usrData
}

func (c *SockConn) setConn(conn net.Conn) {
	c.lock.Lock()
	defer c.lock.Unlock()

	c.conn = conn
	if conn != nil {
		c.readBuff.Reset(conn)
		c.addr = conn.RemoteAddr()
		c.isClose.Store(false)
	} else {
		c.isClose.Store(true)
	}
}

func (c *SockConn) RemoteAddr() net.Addr {
	return c.addr
}

func (c *SockConn) GetId() int32 {
	return c.id
}

func (c *SockConn) Disconnect() {
	if c.isClose.CompareAndSwap(false, true) {
		c.conn.Close()
		c.sendq.Clear()
	}
}

func createSocketConnection(conn net.Conn) *SockConn {
	lvConn := SockConn{
		id:       atomic.AddInt32(&g_connectId, 1),
		readBuff: bufio.NewReader(nil),
		sendq:    &SendQueue{},
	}
	lvConn.setConn(conn)
	return &lvConn
}
